package elijah.eupdater;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;

import com.jeremyliao.liveeventbus.LiveEventBus;

import java.io.File;
import java.util.Locale;
import java.util.Objects;

import elijah.eupdater.bean.Result;
import elijah.eupdater.bean.TerminalDevice;
import elijah.eupdater.databinding.ActivityUpdateBinding;
import elijah.eupdater.rootcommands.RootCommands;
import elijah.eupdater.utils.AppUtils;
import elijah.eupdater.utils.FtpUtils;
import elijah.eupdater.utils.HttpUtils;
import elijah.eupdater.utils.InstallApkUtils;
import es.dmoral.toasty.Toasty;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;


public class UpdateActivity extends AppCompatActivity {
    public static final String KEY_DATA = "KEY_DATA";
    ActivityUpdateBinding binding;

    private static final int INSTALL_PACKAGES_REQUEST = 1112;
    private static final int GET_UNKNOWN_APP_SOURCES = 1113;
    private NetApi netApi;

    private TerminalDevice terminalDevice;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int width = getResources().getDisplayMetrics().widthPixels;
        android.view.WindowManager.LayoutParams p = getWindow().getAttributes();
        p.width = (int) (width * 0.45);
        getWindow().setAttributes(p);
        binding = ActivityUpdateBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        netApi = NetApi.Creator.create(Eupdater.get().getConfig().getHost());

        LiveEventBus.get(KEY_DATA, TerminalDevice.class)
                .observeSticky(this, value -> {
                    terminalDevice = value;
                    binding.tips.setText(String.format("发现新版本%s", terminalDevice.getVersionName()));
                    binding.fileName.setText(terminalDevice.getUpdateFileName());
                    initData(terminalDevice);
                });

        binding.btInstall.setOnClickListener(view -> {
            try {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                    intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
                } else {
                    Uri apkUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".fileProvider", apkFile);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                }
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
                finish();
            } catch (Exception e) {
                e.printStackTrace();
                Toasty.error(getApplicationContext(), "安装异常，" + e).show();
            }
        });


    }

    private void initData(TerminalDevice terminalDevice) {
        Observable<Progress> progressObservable;
        if ("H".equals(terminalDevice.getUpdateType())) {
            progressObservable = HttpUtils.addNewDownload(getContext(), terminalDevice);

        } else {
            progressObservable = FtpUtils.addNewDownload(getContext(), terminalDevice);
        }

        progressObservable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Progress>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        binding.fileName.setText(terminalDevice.getUpdateFileName());
                    }

                    @Override
                    public void onNext(@NonNull Progress process) {
                        binding.progressBar.setProgress((int) process.getProgress());
                        binding.total.setText(String.format(Locale.CHINA, "%.2fM", process.getTotalSize() / 1024f / 1024f));
                        binding.speed.setText(String.format(Locale.CHINA, "%.2fM/s", process.getSpeed() / 1024f / 1024f));
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        showCoverDialog(e.toString());


                    }

                    @Override
                    public void onComplete() {

                        netApi.endUpdate(terminalDevice.getDeviceId(), terminalDevice.getPackageName())
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(new SingleObserver<Result>() {
                                    @Override
                                    public void onSubscribe(Disposable d) {

                                    }

                                    @Override
                                    public void onSuccess(Result result) {
                                        apkFile = new File(AppUtils.getUpdateFilePath(getContext()) + terminalDevice.getUpdateFileName());
                                        Log.i("UPDATE", "update file path: " + apkFile.getPath());
                                        installApp(terminalDevice, apkFile);
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                        apkFile = new File(AppUtils.getUpdateFilePath(getContext()) + terminalDevice.getUpdateFileName());
                                        Log.i("UPDATE", "update file path: " + apkFile.getPath());
                                        installApp(terminalDevice, apkFile);
                                    }
                                });



                    }
                });

    }

    File apkFile;

    public void installApp(TerminalDevice terminalDevice, File apkFile) {
        if (terminalDevice.isManual()) {
            binding.btInstall.setVisibility(View.VISIBLE);
            return;
        }
        if (!RootCommands.rootAccessGiven()) {
            binding.btInstall.setVisibility(View.VISIBLE);
            return;
        }

        try {
            InstallApkUtils.excuteSuCMD(getContext(), apkFile.getPath());
        } catch (Exception e) {
            binding.btInstall.setVisibility(View.VISIBLE);
        }

    }


    public void tendToSettings() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setData(Uri.parse("package:" + getPackageName()));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        startActivity(intent);
    }


    private void showCoverDialog(String msg) {
        Toast.makeText(getApplicationContext(), "更新错误： " + msg, Toast.LENGTH_LONG).show();
        Intent service = new Intent(getContext(), UpdateService.class);
        service.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startService(service);
        finish();

    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //8.0应用设置界面未知安装开源返回时候
        if (requestCode == GET_UNKNOWN_APP_SOURCES && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            boolean allowInstall = Objects.requireNonNull(getContext()).getPackageManager().canRequestPackageInstalls();
            if (allowInstall) {
                binding.btInstall.performClick();
            }
        } else {
            Toast.makeText(getContext(), "您拒绝了安装未知来源应用，应用暂时无法更新！", Toast.LENGTH_SHORT).show();
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == INSTALL_PACKAGES_REQUEST) {
            // 8.0的权限请求结果回调,授权成功
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                binding.btInstall.performClick();
            } else {
                if (getContext() != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    Uri packageUri = Uri.parse("package:" + getContext().getPackageName());
                    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri);
                    startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
                }
            }
        }
    }

    public Context getContext() {
        return this;
    }

    @Override
    public void onBackPressed() {

    }

}
